home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / DiskUtil / Misc / BTNTape.lha / src / btnio.c < prev    next >
C/C++ Source or Header  |  1994-04-03  |  7KB  |  277 lines

  1. /*
  2. **  TapeIO: performs operations to the tape unit via SCSI-direct for BTNtape
  3. **     Version 3.0  03/14/94
  4. **
  5. **   (c) Copyright 1990, 1994  Robert Rethemeyer.
  6. **     This code is freely distributable and redistributable,
  7. **     for non-commercial purposes, provided this notice is included.
  8. **
  9. **   This code was derived from programs written by Robert Mitchell.
  10. */
  11.  
  12. #define _STRICT_ANSI
  13. #include <exec/types.h>
  14. #include <exec/io.h>
  15. #include <libraries/dos.h>
  16. #include <libraries/dosextens.h>
  17. #include <devices/scsidisk.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include "btn.h"
  22. #include "tplink.h"
  23.  
  24. #include <proto/exec.h>
  25. #include <pragmas/exec_pragmas.h>
  26.  
  27. #define DBUG 0
  28.  
  29. /* SCSI commands used by handler */
  30. #define CMD_TEST_UNIT_READY   0x00
  31. #define CMD_REWIND            0x01
  32. #define CMD_REQUEST_SENSE     0x03
  33. #define CMD_SCSI_READ         0x08
  34. #define CMD_SCSI_WRITE        0x0a
  35. #define CMD_FILEMARK          0x10
  36. #define CMD_SPACE             0x11
  37. #define CMD_INQUIRY           0x12
  38. #define CMD_MODE_SELECT       0x15
  39. #define CMD_MODE_SENSE        0x1a
  40. #define CMD_LOAD_UNLOAD       0x1b
  41. #define CMD_READ_CAPACITY     0x25
  42.  
  43. extern UBYTE  *cdb;
  44. extern UBYTE  *sns;
  45. extern UBYTE  *inq;
  46. extern struct SCSICmd  *cmd;
  47. extern UBYTE  *TapeBuff[2];
  48. extern struct IOStdReq *ior;
  49. extern ULONG  blknum;
  50. extern ULONG  blksize;
  51. extern ULONG  numblks;
  52. extern ULONG  TBSize;
  53. extern ULONG  rwlen;
  54. extern ULONG  rdlen;
  55. extern ULONG  expect;
  56. extern ULONG  bugmask;
  57. extern long   filenum;
  58. extern long   lastwrtn;
  59. extern long   actual;
  60. extern long   Boff;
  61. extern long   reserved;
  62. extern long   tpsize;
  63. extern struct tplink  *linktp;
  64. extern BOOL   inprog;
  65. extern BOOL   bswap;
  66. extern BOOL   dbug;
  67. extern char   dbb[80];
  68. extern UBYTE  Lun;
  69. extern UBYTE  varblk;
  70. extern UBYTE  fixedbit;
  71.  
  72. long TapeIO(int toper, long bn, int ctl)
  73. {
  74.  char *z;  int i;  ULONG bc;
  75.  
  76.  if(inprog) {
  77.     WaitIO((struct IORequest *)ior);
  78.     inprog = FALSE;
  79.     if(actual<0) actual = cmd->scsi_Actual;
  80.     if(cdb[0]==CMD_SCSI_READ) Mprintf("%ld bytes\n",actual);
  81.     if(ior->io_Error)  return((long)(ior->io_Error));
  82.  }
  83.  if(toper == TFINISH) return(0L);
  84.  cmd->scsi_Command = cdb;
  85.  cmd->scsi_CmdLength = 6;
  86.  cmd->scsi_Status = 0;
  87.  cmd->scsi_Length = 0;
  88.  cmd->scsi_Actual = 0;
  89.  cmd->scsi_Flags  = 0;
  90.  ior->io_Command = HD_SCSICMD;
  91.  ior->io_Data = (APTR) cmd;
  92.  ior->io_Length = sizeof(struct SCSICmd);
  93.  ior->io_Error = 0;
  94.  for (i=0 ; i<10; i++) cdb[i] = 0x00;
  95.  
  96.  switch(toper) {
  97.  
  98.   case TWRITE:
  99.     if(varblk) bc = expect = cmd->scsi_Length = Boff;
  100.     else {
  101.        bc = ((Boff-1)/blksize)+1;
  102.        cmd->scsi_Length = expect = bc * blksize;
  103.     }
  104.     if(DAC) if((blknum+bc)>tpsize) return(FAKEOM);
  105.     if(bswap) swapbytes(TapeBuff[bn]);
  106.     cdb[0] = CMD_SCSI_WRITE;
  107.     cdb[1] = Lun | fixedbit;
  108.     *((UWORD *)&cdb[2]) = (SEQ) ? (UWORD)(bc>>8) : (UWORD) blknum;
  109.     cdb[4] = (UBYTE) bc & 0xff;
  110.  /* cmd->scsi_Data = (UWORD *) TapeBuff[bn]; */      /* 2090A bug fix */
  111.     cmd->scsi_Data = (UWORD *) ((ULONG) TapeBuff[bn] | bugmask);
  112.     cmd->scsi_Flags = SCSIF_WRITE;
  113.     actual = bc;
  114.     Mprintf("Writing block %lu: %lu bytes\n",blknum,expect);
  115.     break;
  116.  
  117.   case TREAD:
  118.     if(DAC) if((blknum+numblks)>tpsize) return(FAKEOM);
  119.     cdb[0] = CMD_SCSI_READ;
  120.     cdb[1] = Lun | fixedbit;
  121.     *((UWORD *)&cdb[2]) = (SEQ) ? (UWORD)(rdlen>>8) : (UWORD) blknum;
  122.     cdb[4] = (UBYTE) rdlen & 0xff;
  123.     cmd->scsi_Data = (UWORD *) TapeBuff[bn];
  124.     cmd->scsi_Length = expect = rwlen;
  125.     cmd->scsi_Flags = SCSIF_READ;
  126.     actual = -1;
  127.     Mprintf("Reading block %lu:",blknum);
  128.     break;
  129.  
  130.   case TSENSE:
  131.     for (i=0 ; i<32; i++) sns[i] = 0;
  132.     cdb[0] = CMD_REQUEST_SENSE;
  133.     cdb[1] = Lun;
  134.     cdb[4] = 32;  /* extended sense */
  135.     cmd->scsi_Length = 32;
  136.     cmd->scsi_Data = (UWORD *) sns;
  137.     cmd->scsi_Flags = SCSIF_READ;
  138.     break;
  139.  
  140.   case TREWIND:
  141.     cdb[0] = CMD_REWIND;
  142.     cdb[1] = Lun;
  143.     filenum = reserved;
  144.     lastwrtn = -1;
  145.     Mprintf("Rewinding\n");
  146.     break;
  147.  
  148.   case INQUIRY:  /* read drive information */
  149.     cdb[0] = CMD_INQUIRY;
  150.     cdb[1] = Lun;
  151.     cdb[4] = 36;
  152.     cmd->scsi_Length = 36;
  153.     cmd->scsi_Data = (UWORD *) inq;
  154.     cmd->scsi_Flags = SCSIF_READ;
  155.     break;
  156.  
  157.   case TREADY:  /* test unit ready */
  158.     cdb[0] = CMD_TEST_UNIT_READY;
  159.     cdb[1] = Lun;
  160.     break;
  161.  
  162.   case MDSNS:
  163.     for (i=0 ; i<12; i++) sns[i] = 0;
  164.     cdb[0] = CMD_MODE_SENSE;
  165.     cdb[1] = Lun;
  166.     cdb[4] = 12;
  167.     cmd->scsi_Length = 12;
  168.     cmd->scsi_Data = (UWORD *) sns;
  169.     cmd->scsi_Flags = SCSIF_READ;
  170.     break;
  171.  
  172.   case WFMARK:  /* write file mark */
  173.     cdb[0] = CMD_FILEMARK;
  174.     cdb[1] = Lun;
  175.     cdb[4] = (UBYTE) bn;
  176.     if(bn) Mprintf("Writing filemark\n");
  177.     break;
  178.  
  179.   case TSKIPF:   /* skip over filemarks */
  180.     cdb[0] = CMD_SPACE;
  181.     cdb[1] = Lun | 0x01;
  182.     cdb[2] = (UBYTE) (bn >> 16);
  183.     cdb[3] = (UBYTE) (bn >> 8);
  184.     cdb[4] = (UBYTE)  bn;
  185.     break;
  186.  
  187.   case TSKIPE:   /* skip to end-of-data */
  188.     cdb[0] = CMD_SPACE;
  189.     cdb[1] = Lun | 0x03;
  190.     Mprintf("Skipping to end of data\n");
  191.     break;
  192.  
  193.   case TRETEN:  /* retension tape */
  194.     cdb[0] = CMD_LOAD_UNLOAD;
  195.     cdb[1] = Lun;
  196.     cdb[4] = 0x03;
  197.     Mprintf("Retensioning\n");
  198.     break;
  199.  
  200.   case TEJECT:  /* eject tape */
  201.     cdb[0] = CMD_LOAD_UNLOAD;
  202.     cdb[1] = Lun;
  203.     cdb[4] = 0x00;
  204.     Mprintf("Ejecting tape\n");
  205.     break;
  206.  
  207.   case RDCAP:  /* read tape capacity.  3M drive only */
  208.     cdb[0] = CMD_READ_CAPACITY;
  209.     cdb[1] = Lun;
  210.     cmd->scsi_CmdLength = 10;
  211.     cmd->scsi_Length = 8;
  212.     cmd->scsi_Data = (UWORD *) sns;
  213.     cmd->scsi_Flags = SCSIF_READ;
  214.     break;
  215.  
  216.   case RAWCMD:  /* write user-provided control command */
  217.     i = 0;
  218.     z = (char *)TapeBuff[bn];
  219.     while(*z!='\n' && i<10)  cdb[i++] = (UBYTE) strtoul(z,&z,16);
  220.     cdb[1] |= Lun;
  221.     if(cdb[0] == CMD_REWIND) { blknum = filenum = reserved;  lastwrtn = -1; }
  222.     if(cdb[0] >= 0x20) cmd->scsi_CmdLength = 10;
  223.     if(cdb[0] >= 0xa0) cmd->scsi_CmdLength = 12;
  224.     cmd->scsi_Data = (UWORD *) sns;
  225.     Mprintf("Raw command %02X\n",cdb[0]);
  226.     break;
  227.  
  228.   case MDSET:  /* set fixed-mode block length */
  229.     cdb[0] = CMD_MODE_SELECT;
  230.     cdb[1] = Lun;
  231.     cdb[4] = 12;
  232.     for (i=0 ; i<12; i++) sns[i] = 0x00;
  233.     sns[2] = 0x10;  /* buffered mode */
  234.     sns[3] = 8;
  235.     if(!bn) *((ULONG *)&sns[8]) = blksize & 0x00ffffff; /* block length */
  236.     cmd->scsi_Length = 12;
  237.     cmd->scsi_Data = (UWORD *) sns;
  238.     cmd->scsi_Flags = SCSIF_WRITE;
  239.     Mprintf("Mode Select, new block size %lu\n",blksize);
  240.     break;
  241.  
  242.   case USRMODE:  /* write user-provided mode-select data */
  243.     for (i=0 ; i<64; i++) sns[i] = 0x00;
  244.     i = 0;
  245.     z = (char *)TapeBuff[bn];
  246.     while(*z!='\n' && i<64)  sns[i++] = (UBYTE) strtoul(z,&z,16);
  247.     cdb[0] = CMD_MODE_SELECT;
  248.     cdb[1] = Lun;
  249.     cdb[4] = i;
  250.     cmd->scsi_Length = i;
  251.     cmd->scsi_Data = (UWORD *) sns;
  252.     cmd->scsi_Flags  = SCSIF_WRITE;
  253.     Mprintf("User Mode-Select\n");
  254.     break;
  255.  
  256.   }
  257.  
  258. #ifdef DBUG
  259.   if(dbug) Mprintf("CDB= %02X %02X %02X %02X %02X %02X  ADR=%08X LEN=%X\n",
  260.             cdb[0],cdb[1],cdb[2],cdb[3],cdb[4],cdb[5],
  261.             cmd->scsi_Data, cmd->scsi_Length);
  262. #endif
  263.  
  264.   if(ctl == CTLWAIT) {
  265.        DoIO ((struct IORequest *)ior);    /* start sync io */
  266.        if(actual<0) actual = cmd->scsi_Actual;
  267.        if(cdb[0]==CMD_SCSI_READ) Mprintf("%ld bytes\n",actual);
  268.        return((long)(ior->io_Error));
  269.   }
  270.   else {
  271.        SendIO((struct IORequest *)ior);  /* start async io */
  272.        inprog = TRUE;
  273.        return(0L);
  274.   }
  275. }
  276.  
  277.